package org.je.json;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/***
 * 表示一个Json对象
 * 
 * @author fan yi feng
 */
public class Json
{
	// public int endIndexInList=-1;

	private final Map<String, Object>	map	= new LinkedHashMap<String, Object>();

	public Map<String, Object> getMap() {
		return map;
	}

	public int size() {
		return map.size();
	}

	/**
	 * @param name
	 * @param value
	 */
	public void set(String name, Object value) {
		map.put(name, value);
	}

	/**
	 * @param name
	 * @param value
	 */
	@SuppressWarnings("unchecked")
	public void add(String name, Object value) {
		Object obj = map.get(name);
		if (obj == null) {
			map.put(name, value);
		} else {
			if (obj instanceof List) {
				List<Object> arr = (ArrayList<Object>) obj;
				arr.add(value);
			} else {
				List<Object> arr = new ArrayList<Object>(5);
				arr.add(obj);
				arr.add(value);
				map.put(name, arr);
			}
		}
	}

	/**
	 * @param name
	 * @return
	 */
	public Object get(String name) {
		return map.get(name);
	}

	/**
	 * @param name
	 * @return JsonArray
	 */
	public JsonArray getArray(String name) {
		Object obj = get(name);
		if (obj == null)
			return null;
		return (JsonArray) obj;
	}

	/**
	 * @param name
	 * @return Json
	 */
	public Json getJson(String name) {
		Object obj = get(name);
		if (obj == null)
			return null;
		return (Json) obj;
	}

	/**
	 * @param name
	 * @return str
	 */
	public String getString(String name) {
		Object obj = get(name);
		if (obj == null)
			return null;
		return obj.toString();
	}

	/**
	 * @param name
	 * @return
	 */
	public int getInt(String name) {
		Object obj = get(name);

		if (obj == null)
			return 0;
		if (obj instanceof Integer)
			return (Integer) obj;
		if (obj instanceof Long) {
			long d = (Long) obj;
			return (int) d;
		}
		if (obj instanceof String)
			return Integer.parseInt((String) obj);
		throw new RuntimeException(obj + " 不能转换为int");
	}

	/**
	 * @param name
	 * @return
	 */
	public long getLong(String name) {
		Object obj = get(name);
		if (obj == null)
			return 0;
		if (obj instanceof Integer) {
			int d = (Integer) obj;
			return d;
		}
		if (obj instanceof Long)
			return (Long) obj;

		if (obj instanceof String)
			return Long.parseLong((String) obj);

		throw new RuntimeException(obj + " 不能转换为long");
	}

	@Override
	public String toString() {
		return toJsonString(0);
	}

	private String toJsonString(int level) {
		level = level < 0 ? 0 : level;
		return getJsonString(this, level);
	}

	static String getJsonString(Json obj, int num) {
		StringBuilder bf = new StringBuilder();
		bf.append(getLevel(num) + "{\r\n");

		int count = 0;

		for (Map.Entry<String, Object> en : obj.getMap().entrySet()) {
			bf.append(getLevel(num + 1) + makeString(en.getKey()) + ":");

			Object value = en.getValue();

			if (value instanceof Json) {
				bf.append("\r\n" + getJsonString((Json) value, num + 1));
			} else if (value instanceof JsonArray) {
				bf.append("\r\n" + JsonArray.getArrayString((JsonArray) value, num + 1));
			} else {
				bf.append(dealStr(value == null ? null : value.toString()));
			}

			++count;

			if (count != obj.size())
				bf.append(",");

			bf.append("\r\n");
		}
		bf.append(getLevel(num) + "}");
		return bf.toString();
	}

	static String getLevel(int num) {
		StringBuilder bf = new StringBuilder();
		for (int i = 0; i < num; ++i) {
			bf.append(' ');
		}
		return bf.toString();
	}

	static String dealStr(String str) {
		if (str == null)
			return "null";

		if (str.equals("true") || str.equals("false") || str.equals("null")) {
			return str;
		}
		return makeString(str);
	}

	private static String makeString(String str) {
		if (str == null)
			return null;

		StringBuilder bf = new StringBuilder();
		bf.append('\"');

		for (int i = 0; i < str.length(); ++i) {
			char c = str.charAt(i);
			if (c == '\\') {
				if (i == str.length() - 1) {
					bf.append("\\\\");
				} else {
					char c2 = str.charAt(i + 1);
					if (c2 == '\'') {
						bf.append('\'');
						++i;
						continue;
					} else {
						bf.append("\\" + c2);
						++i;
						continue;
					}
				}
			} else if (c == '\"') {
				bf.append("\\\"");
			} else if (c == '\t') {
				bf.append("\\t");
			} else if (c == '\r') {
				bf.append("\\r");
			} else if (c == '\n') {
				bf.append("\\n");
			} else {
				bf.append(c);
			}
		}
		bf.append('\"');
		return bf.toString();
	}
}
